<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="val in item.values" :key="val.name">
          <img
            :title="val.name"
            v-if="val.picture"
            :class="{ selected: val.selected, disabled: val.disable }"
            :src="val.picture"
            alt=""
            @click="selectSku(val, item.values)"
          />
          <span
            v-else
            @click="selectSku(val, item.values)"
            :class="{ selected: val.selected, disabled: val.disable }"
            >{{ val.name }}</span
          ></template
        >
      </dd>
    </dl>
  </div>
</template>

<script>
import powerSet from 'views/vender/powerSet.js'
const spliter = '★'
// 1、获得所有sku集合
const getPathMap = (skus) => {
  const pathMap = {}
  skus.forEach((item) => {
    // 2、从sku中筛选有效sku
    if (item.inventory > 0) {
      // 3、powerSet得到子集
      const valueArr = powerSet(item.specs.map((val) => val.valueName))
      valueArr.shift()
      valueArr.forEach((arr) => {
        // arr拿字符串key，key用拼接符拼接字符串:['蓝色','中国']==>['蓝色★中国']
        const key = arr.join(spliter)
        // 字典添加
        // 4、根据子集写字典，储存对象key-value
        if (pathMap[key]) {
          pathMap[key].push(item.id)
        } else {
          // 储存成数组的形式，因为一个key可能对应多个id，比如规格20寸，有5个颜色有库存，就有5个id
          pathMap[key] = [item.id]
        }
      })
    }
  })
  return pathMap
}
// 2、按钮禁用，这个解决方案会有很多无用操作
const updateDisableBtn = (specs, pathMap) => {
  // 规格
  specs.forEach((item, i) => {
    const selectedValue = selectedValues(specs)
    // 详细参数
    item.values.some((val) => {
      if (val.selected) return true
      else {
        selectedValue[i] = val.name
        const key = selectedValue.filter((value) => value).join(spliter)
        // 是否有该数据
        val.disable = !pathMap[key]
        return false
      }
    })
    /*
    *这个老师用的forEach，这个解决方案会有很多无用操作，因为当我选中了一个规格内的那内容后，
    *我并不需要遍历这一行规格的参数了，应该直接跳出，到下一个规格。由于forEach无法直接跳出循环，
    some和every都可以跳出，这里我用了some，但选中的前面的参数，还是会遍历
    为了打印更清楚的话，其实还可以用find遍历一遍该规格是否有被选中，如果被选中直接跳出
    */
    // item.values.forEach((val) => {
    //   console.log(val);
    //   if (val.selected) return;
    //   selectedValue[i] = val.name;
    //   const key = selectedValue.filter((value) => value).join(spliter);
    //   console.log(key);
    //   //是否有该数据
    //   val.disable = !pathMap[key];
    // });
  })
}
// 3、禁用的组合逻辑
const selectedValues = (specs) => {
  const arr = []
  specs.forEach((item) => {
    // 先选择已经被选中的按钮
    const selectedVal = item.values.find((val) => val.selected)
    // 有值就推进去，没值就undefind
    arr.push(selectedVal ? selectedVal.name : undefined)
  })
  return arr
}
// 4、初始化默认选中
const initDefaultSelected = (goods, skuId) => {
  const good = goods.skus.find((item) => item.id === skuId)
  goods.specs.forEach((spec, i) => {
    spec.values.forEach((val) => {
      val.selected = val.name === good.specs[i].valueName
    })
  })
}
export default {
  name: 'GoodsSku',
  props: {
    goods: {
      type: Object,
      default: () => ({})
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  setup (props, { emit }) {
    const pathMap = getPathMap(props.goods.skus)
    // console.log(props.goods.skus);
    updateDisableBtn(props.goods.specs, pathMap)
    if (props.skuId) initDefaultSelected(props.goods, props.skuId)
    const selectSku = (val, all) => {
      // 如果没货被禁用，不可点
      if (val.disable) {
        return
      }
      // 如果当前为选中，点击为未选中
      if (val.selected) {
        val.selected = false
      }
      // 如果当前未选中，点击选中，则需要把其他的选中的去除
      else {
        all.forEach((item) => {
          item.selected = false
        })
        val.selected = true
      }

      updateDisableBtn(props.goods.specs, pathMap)
      // 信息发送，当选择完整，有skuid的时候才传信息，若不是完整的sku，则提交空
      const validSelectedVal = selectedValues(props.goods.specs).filter(
        (val) => val
      )
      if (props.goods.specs.length === validSelectedVal.length) {
        const skuIds = pathMap[validSelectedVal.join(spliter)]
        const sku = props.goods.skus.find((sku) => sku.id === skuIds[0])
        emit('change', {
          skuId: sku.id,
          price: sku.price,
          oldPrice: sku.oldPrice,
          inventory: sku.inventory,
          specsText: sku.specs
            .reduce((p, n) => `${p} ${n.name}：${n.valueName}`, '')
            .trim()
        })
      } else {
        emit('change', {})
      }
    }

    return { selectSku }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  margin-bottom: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 0.8;
      flex-wrap: wrap;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
